package com.xs.gis.cover.coverImpl;

import com.xs.gis.cover.FileCover;
import com.xs.gis.cover.MultipleFileCover;
import com.xs.gis.domain.geojson.GeoFeature;
import com.xs.gis.domain.geojson.GeoJsonFeature;
import com.xs.gis.enums.CoverConstant;
import com.xs.gis.util.GisCommonUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.gdal.gdal.gdal;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.Driver;
import org.gdal.ogr.Layer;
import org.gdal.ogr.ogr;
import org.gdal.osr.SpatialReference;

import java.util.ArrayList;
import java.util.List;

import static com.xs.gis.enums.CoverConstant.DIVER_GDB;

/**
 *  Gdb是 Esri 公司 ArcGIS 平台的核心数据模型，gdb有多个图层
 * @Description  GdbCover
 * @Author guoyb
 * @Date   2025/7/1 16:22
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
public class GdbCover implements FileCover, MultipleFileCover {


    private String defaultEpsgCode = "4490";


    @Override
    public String featureToFile(GeoJsonFeature feature, String filePath) {


        gdal.AllRegister();
        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");

        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(DIVER_GDB);

        if (oDriver == null) {
            throw new RuntimeException(" FileGDB驱动不可用");
        }

        GisCommonUtils.deleteExistsFile(filePath);
        DataSource dataSourceGDB = oDriver.CreateDataSource(filePath);
        List<GeoFeature> features = feature.getFeatures();

        //创建图层
        String epsgCode = StringUtils.isBlank(feature.getEpsgCode()) ? defaultEpsgCode : feature.getEpsgCode();
        Layer gdbLayer = GisCommonUtils.createLayer(feature, dataSourceGDB, epsgCode, CoverConstant.GDB_IGNORE_FIELD);

        //添加数据
        GisCommonUtils.addGdbData(features, gdbLayer, epsgCode);

        gdbLayer.delete();
        dataSourceGDB.delete();
        gdal.GDALDestroyDriverManager();
        return filePath;
    }


    @Override
    public GeoJsonFeature fileToFeature(String filePath) {

        ogr.RegisterAll();
        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
        // 读取数据，这里以gdb文件为例
        // 创建一个文件，根据strDriverName扩展名自动判断驱动类型
        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(DIVER_GDB);
        if (oDriver == null) {
            throw new RuntimeException("驱动不可用!");
        }
        DataSource dataSource = oDriver.Open(filePath, 0);

        GeoJsonFeature geoJsonFeature = new GeoJsonFeature();

        int layerCount = dataSource.GetLayerCount();
        if (layerCount > 0) {
            Layer layer = dataSource.GetLayer(0);
            geoJsonFeature.setLayerName(layer.GetName());
            //设置图层名和参考系
            SpatialReference spatialReference = layer.GetSpatialRef();
            String epscCode = spatialReference == null ? defaultEpsgCode : spatialReference.GetAttrValue("AUTHORITY", 1);


            List<GeoFeature> features = GisCommonUtils.layerFeatureToFeature(epscCode, geoJsonFeature, layer);

            layer.delete();
            geoJsonFeature.setFeatures(features);
        }
        dataSource.delete();
        gdal.GDALDestroyDriverManager();


        return geoJsonFeature;
    }


    @Override
    public String featureToMultipleFile(List<GeoJsonFeature> features, String filePath) {


        ogr.RegisterAll();
        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
        // 读取数据，这里以gdb文件为例
        // 创建一个文件，根据strDriverName扩展名自动判断驱动类型
        Driver oDriver = ogr.GetDriverByName(DIVER_GDB);
        if (oDriver == null) {
            throw new RuntimeException("驱动不可用!");
        }
        GisCommonUtils.deleteExistsFile(filePath);

        DataSource dataSourceGDB = oDriver.CreateDataSource(filePath);

        for (GeoJsonFeature feature : features) {
            //创建图层
            String epsgCode = StringUtils.isBlank(feature.getEpsgCode()) ? defaultEpsgCode : feature.getEpsgCode();
            Layer gdbLayer = GisCommonUtils.createLayer(feature, dataSourceGDB, epsgCode);
            //添加数据
            GisCommonUtils.addGdbData(feature.getFeatures(), gdbLayer, epsgCode);
            gdbLayer.delete();
        }
        dataSourceGDB.delete();
        gdal.GDALDestroyDriverManager();


        return filePath;
    }


    /**
     * 解析多文件
     *
     * @param filePath
     * @return
     */
    @Override
    public List<GeoJsonFeature> multipleFileToFeature(String filePath) {

        ogr.RegisterAll();
        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
        // 创建一个文件，根据strDriverName扩展名自动判断驱动类型
        Driver oDriver = ogr.GetDriverByName(DIVER_GDB);
        if (oDriver == null) {
            throw new RuntimeException("驱动不可用!");
        }
        DataSource dataSource = oDriver.Open(filePath, 0);

        List<GeoJsonFeature> geoJsonFeatures = new ArrayList<>();
        try {
            int layerCount = dataSource.GetLayerCount();

            for (int i = 0; i < layerCount; i++) {
                GeoJsonFeature geoJsonFeature = new GeoJsonFeature();
                Layer layer = dataSource.GetLayer(i);
                geoJsonFeature.setLayerName(layer.GetName());
                //设置图层名和参考系
                SpatialReference spatialReference = layer.GetSpatialRef();
                String epscCode = spatialReference == null ? defaultEpsgCode : spatialReference.GetAttrValue("AUTHORITY", 1);

                List<GeoFeature> features = GisCommonUtils.layerFeatureToFeature(epscCode, geoJsonFeature, layer);

                geoJsonFeature.setFeatures(features);
                geoJsonFeatures.add(geoJsonFeature);
                layer.delete();

            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        dataSource.delete();
        gdal.GDALDestroyDriverManager();

        return geoJsonFeatures;
    }


}
